package org.dromara.system.util;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;

/**
 * @author 王星
 * @date 2024/6/4 下午5:44
 */
public class JacksonFactory {

    public static ObjectMapper newObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        //主要目的是为了正确处理非驼峰命名
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        final SimpleModule module = new SimpleModule();
        module.addSerializer(Long.class, new ToStringSerializer()); //可以考虑只针对mvc,毕竟只有前端JS才有Long溢出问题
        objectMapper.registerModule(module);
        // 忽略在json字符串中存在，但是在java对象中不存在对应属性的情况
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 忽略空Bean转json的错误
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 允许不带引号的字段名称
        objectMapper.configure(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES.mappedFeature(), true);
        // 允许单引号
        objectMapper.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true);
        // allow int startWith 0
        objectMapper.configure(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature(), true);
        // 允许字符串存在转义字符：\r \n \t
        objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
        // 排除空值字段
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        objectMapper.setDateFormat(new SimpleDateFormat(CommonConstant.DATETIME_FORMAT));
        objectMapper.setTimeZone(TimeZone.getTimeZone(CommonConstant.TIME_ZONE_GMT8));

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(new LocalDateTimeSerializer(DateTimeFormatter
                .ofPattern(CommonConstant.DATETIME_FORMAT)))
            .addDeserializer(LocalDateTime.class,
                new LocalDateTimeDeserializer(DateTimeFormatter
                    .ofPattern(CommonConstant.DATETIME_FORMAT)));
        simpleModule.addSerializer(new LocalTimeSerializer(DateTimeFormatter
                .ofPattern(CommonConstant.TIME_FORMAT)))
            .addDeserializer(LocalTime.class,
                new LocalTimeDeserializer(DateTimeFormatter
                    .ofPattern(CommonConstant.TIME_FORMAT)));

        simpleModule.addSerializer(new LocalDateSerializer(DateTimeFormatter
                .ofPattern(CommonConstant.YYYY_MM_DD)))
            .addDeserializer(LocalDate.class,
                new LocalDateDeserializer(DateTimeFormatter
                    .ofPattern(CommonConstant.YYYY_MM_DD)));
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}
